package com.ideal.frame.sys.service;


import cn.hutool.core.lang.Assert;
import com.ideal.frame.jpa.DSLRequest;
import com.querydsl.core.BooleanBuilder;
import com.ideal.frame.jpa.DSLPageRequest;
import com.ideal.frame.jpa.JpaRepositoryImpl;
import com.ideal.frame.sys.entity.QSysDict;
import com.ideal.frame.sys.entity.SysDict;
import com.ideal.frame.sys.form.search.DictSearchForm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class SysDictService {
    @PersistenceContext
    protected EntityManager entityManager;
    private JpaRepositoryImpl<SysDict, Long> dictRepo;

    QSysDict qSysDict = QSysDict.sysDict;

    @PostConstruct
    public void initRepo() {
        dictRepo = new JpaRepositoryImpl<>(SysDict.class, entityManager);
    }

    /**
     * 根据id获取字典详细信息
     *
     * @param id
     * @return
     */
    public SysDict getOne(Long id) {
        Optional<SysDict> dict = dictRepo.findById(id);
        return dict.isPresent() ? dict.get() : null;
//        return dictRepo.getOne(id);
    }

    /**
     * 保存字典信息
     *
     * @param sysDict
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SysDict save(SysDict sysDict) {
        BooleanBuilder builder = new BooleanBuilder(qSysDict.label.eq(sysDict.getLabel()));
        if (sysDict.getParentId() == null) {
            builder.and(qSysDict.parentId.isNull());
        } else {
            builder.and(qSysDict.parentId.eq(sysDict.getParentId()));
        }
        if (sysDict.getId() != null) {
            builder.andNot(qSysDict.id.eq(sysDict.getId()));
        }
        sysDict.setDelFlag(false);
        Assert.isFalse(dictRepo.exists(builder), "当前字典已存在");
        return dictRepo.save(sysDict);
    }

    /**
     * 根据id删除字典信息
     *
     * @param ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        //先删除子项，然后删除自己
        dictRepo.update(qSysDict).set(qSysDict.delFlag, true).where(qSysDict.parentId.in(ids)).execute();
        dictRepo.update(qSysDict).set(qSysDict.delFlag, true).where(qSysDict.id.in(ids)).execute();
    }

    /**
     * 一次性获取所有字典
     * xuchun
     * 2019-11-19
     *
     * @return
     */
    public Map<String, List<Map<String, String>>> getSysDict() {
//        List<Tuple> list = queryFactory.select(qSysDict.id, qSysDict.code, qSysDict.label)
//                .from(qSysDict).where(qSysDict.parentId.isNull()).fetch();
//        if (list != null && !list.isEmpty()) {
//            Map<String, List<Map<String, String>>> dictMap = new HashMap<>();
//            for (Tuple dict : list) {
//                QSysDict dictQ = QSysDict.sysDict;
//                List<Tuple> listChild = queryFactory.select(dictQ.code, dictQ.label).from(dictQ).where(dictQ.parentId.eq(dict.get(dictQ.id))).fetch();
//                if (listChild != null && !listChild.isEmpty()) {
//                    List<Map<String, String>> listMap = new ArrayList<>();
//                    for (Tuple c : listChild) {
//                        Map<String, String> childMap = new HashMap<>();
//                        childMap.put("code", c.get(dictQ.code));
//                        childMap.put("label", c.get(dictQ.label));
//                        listMap.add(childMap);
//                    }
//                    dictMap.put(dict.get(dictQ.code), listMap);
//                } else {
//                    dictMap.put(dict.get(dictQ.code), new ArrayList<>());//放一个空的，code下面字典列表是个空数组，防止前端js获取问题
//                }
//
//            }
//            return dictMap;
//        }
        return null;
    }

    /**
     * 获取字典列表分页
     *
     * @param form
     * @return
     */
    public Page<SysDict> getPage(DictSearchForm form) {
        DSLPageRequest pageRequest = form.asDslPageRequest();
        pageRequest.addWhere(form.getParentId() == null ? qSysDict.parentId.isNull() : qSysDict.parentId.eq(form.getParentId()));
        if (StringUtils.isNotEmpty(form.getLabel())) {
            pageRequest.addWhere(qSysDict.label.like("%" + form.getLabel() + "%"));
        }
        if (StringUtils.isNotEmpty(form.getCode())) {
            pageRequest.addWhere(qSysDict.code.like("%" + form.getCode() + "%"));
        }
        pageRequest.addWhere(qSysDict.delFlag.isFalse());
        pageRequest.addOrderBy(qSysDict.sort.asc());
        return dictRepo.findAll(pageRequest);
    }

    /**
     * 根据id获取子级字典列表
     *
     * @param id
     * @return
     */
    public List<SysDict> getChildById(Long id) {
        DSLRequest request = new DSLRequest();
        request.addWhere(qSysDict.parentId.eq(id));
        request.addWhere(qSysDict.delFlag.isFalse());
        request.addOrderBy(qSysDict.sort.asc());
        List<SysDict> list = dictRepo.findAll(request);
        return list;
    }

    /**
     * 根据字典编码获取子级字典信息
     *
     * @param code
     * @return
     */
    public List<SysDict> getChildByCode(String code) {
        SysDict dict = dictRepo.selectFrom(qSysDict).where(qSysDict.code.eq(code)).where(qSysDict.parentId.isNull()).fetchFirst();
        return getChildById(dict.getId());
    }

    private SysDict getByCode(String code) {
//        BooleanBuilder where = new BooleanBuilder();
//        where.and(qSysDict.code.eq(code));
//        return jpaRepo.findOne(where);
        return null;
    }
}
